package com.gt.wxpay.cashier.payment.application.impl;

import com.gt.wxpay.cashier.domain.model.CashierPayment;
import com.gt.wxpay.cashier.domain.model.RefundStatusEnum;
import com.gt.wxpay.cashier.domain.model.TransactionTypeEnum;
import com.gt.wxpay.cashier.payment.application.CheckCommonService;
import com.gt.wxpay.cashier.payment.application.MerchantRefundHandlerService;
import com.gt.wxpay.cashier.payment.application.ModifyAccountService;
import com.gt.wxpay.cashier.payment.application.PaymentService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * packageName com.gt.wxpay.cashier.payment.application.impl
 *
 * @author GuoTong
 * @version JDK 8
 * @className MerchantRefundHandlerService
 * @date 2024/3/25
 * @description 商户退款处理流程
 */
@Service
public class MerchantRefundHandlerServiceImpl implements MerchantRefundHandlerService {

    private Logger logger = LoggerFactory.getLogger(MerchantRefundHandlerServiceImpl.class);

    /**
     * 动账操作基础服务
     */
    @Autowired
    private ModifyAccountService modifyAccountService;

    @Autowired
    private TaskExecutor taskExecutor;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private CheckCommonService checkCommonService;

    @Autowired
    private NotifyOperationsPersonnelImpl notifyOperationsPersonnel;

    /**
     * 订单退款流程---商户退款处理流程
     * 退款的订单cashierPayment
     *
     * @param cashierPayment cashierPayment
     */
    @Override
    public void refundHandler(CashierPayment cashierPayment) {
        // 微信退款 校验必要参数
        String checkMsg = checkCommonService.checkRefundInMerchant(cashierPayment);
        if (checkMsg != null) {
            throw new RuntimeException(checkMsg);
        }
        // 1. 判断支付订单是否已结算 || checkStatus对账状态（-1-帐不平，0-未对账，1-帐平）
        Integer checkStatus = cashierPayment.getCheckStatus();
        // 获取商户号
        String merchantId = cashierPayment.getMerchantId();
        // 商户退款处理流程商户侧动账状态
        boolean modifyAccountStatus = false;
        StringBuilder failMsg = new StringBuilder();
        switch (checkStatus) {
            case -1:
                logger.error("退款处理流程：订单{}帐不平，暂时无法退款", cashierPayment.getPaymentNo());
                break;
            case 1:
                logger.info("退款处理流程：订单{}帐平，开始商户基本账户余额退款", cashierPayment.getPaymentNo());
                // 2. 调用商户基本账户余额退款接口
                modifyAccountStatus = modifyAccountService.modifyBaseAccountBalanceByMerchantRefund(merchantId, cashierPayment);
                failMsg.append("订单").append(cashierPayment.getPaymentNo()).append(",商户基本账户余额退款==>").append(modifyAccountStatus);
                logger.info(failMsg.toString());
                break;
            default:
                logger.info("退款处理流程：订单{},未对账--代表未结算--直接走商户应收账户退款", cashierPayment.getPaymentNo());
                // 2. 调用商户商户应收账户余额退款接口
                modifyAccountStatus = modifyAccountService.modifyReceivableAccountBalanceByMerchantRefund(merchantId, cashierPayment);
                failMsg.append("订单").append(cashierPayment.getPaymentNo()).append(",商户应收账户余额退款==>").append(modifyAccountStatus);
                logger.info(failMsg.toString());
                break;
        }
        // 3. 更新商户侧--退款状态
        cashierPayment.setMerchantRefundStatus(modifyAccountStatus ? RefundStatusEnum.SUCCESS.getCode() : RefundStatusEnum.ABNORMAL.getCode());
        paymentService.updateById(cashierPayment);
        if (modifyAccountStatus) {
            // 4. 商户应收账户余额退款成功--发起渠道侧退款流程 ====>异步处理
            taskExecutor.execute(() -> paymentService.refund(cashierPayment));
        } else {
            // 商户侧退款失败---通知运营人员:
            notifyOperationsPersonnel.sendOperationsMessageRefundFail(merchantId, cashierPayment, failMsg.toString());
        }
    }

    /**
     * 商户充值流程处理---退款失败订单进入退款
     * cashierPayment|原始商户侧退款失败的订单
     *
     * @param merchantId merchantId
     */
    @Override
    public void merchantRechargePostProcessing(String merchantId) {
        // 获取失败的枚举值
        Integer merchantRefundAbnormalValue = RefundStatusEnum.ABNORMAL.getCode();
        // 获取交易类型退款
        Integer TransactionTypeValue = TransactionTypeEnum.REFUND.code();
        // 获取商户的所有退款失败的订单----重新发起退款
        List<CashierPayment> listFailOrder = paymentService.listAllByThatMerchantFailRefundOrder(merchantId, merchantRefundAbnormalValue, TransactionTypeValue);
        if (CollectionUtils.isEmpty(listFailOrder)) {
            return;
        }
        for (CashierPayment cashierPayment : listFailOrder) {
            this.refundHandler(cashierPayment);
        }
    }

    /**
     * 商户结算流程处理---退款失败订单进入退款
     * cashierPayment|原始商户侧退款失败的订单
     *
     * @param merchantId merchantId
     */
    @Override
    public void merchantBalancePostProcessing(String merchantId) {
        this.merchantRechargePostProcessing(merchantId);
    }


    /**
     * 订单退款---走平台垫付流程
     *
     * @param cashierPayment cashierPayment
     */
    @Override
    public void usePlatformAdvancePayment(CashierPayment cashierPayment) {
        // 更新商户侧--退款状态|走平台垫付流程 直接商户侧成功
        cashierPayment.setMerchantRefundStatus(RefundStatusEnum.SUCCESS.getCode());
        paymentService.updateById(cashierPayment);
        // 更新平台侧--退款状态
        taskExecutor.execute(() -> paymentService.refund(cashierPayment));
    }
}
